/* eslint-disable */

const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const WebpackBuildNotifierPlugin = require("webpack-build-notifier");
const ManifestPlugin = require("webpack-manifest-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const LessPluginAutoPrefix = require("less-plugin-autoprefix");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
// const TerserPlugin = require('terser-webpack-plugin');
const fs = require("fs");
// const CompressionWebpackPlugin = require('compression-webpack-plugin');
// const productionGzipExtensions = /\.(js|css|json|ttf)(\?.*)?$/i

const path = require("path");

function optionalRequire(module, defaultReturn = undefined) {
  try {
    require.resolve(module);
  } catch (e) {
    if (e && e.code === "MODULE_NOT_FOUND") {
      // Module was not found, return default value if any
      return defaultReturn;
    }
    throw e;
  }
  return require(module);
}

// Load optionally configuration object (see scripts/README)
const CONFIG = optionalRequire("./scripts/config", {});

const isProduction = process.env.NODE_ENV === "production";

const redashBackend = process.env.REDASH_BACKEND || "http://localhost:5000";
const baseHref = CONFIG.baseHref || "/";
const staticPath = CONFIG.staticPath || "/static/";
const htmlTitle = CONFIG.title || "首页";

const basePath = path.join(__dirname, "client");
const appPath = path.join(__dirname, "client", "app");

const extensionsRelativePath =
  process.env.EXTENSIONS_DIRECTORY || path.join("client", "app", "extensions");
const extensionPath = path.join(__dirname, extensionsRelativePath);

// Function to apply configuration overrides (see scripts/README)
function maybeApplyOverrides(config) {
  const overridesLocation = process.env.REDASH_WEBPACK_OVERRIDES || "./scripts/webpack/overrides";
  const applyOverrides = optionalRequire(overridesLocation);
  if (!applyOverrides) {
    return config;
  }
  console.info("Custom overrides found. Applying them...");
  const newConfig = applyOverrides(config);
  console.info("Custom overrides applied successfully.");
  return newConfig;
}

const config = {
  mode:  "production" ,
  entry: {
    app: [
      "./client/app/index.js",
      "./client/app/assets/less/main.less",
      "./client/app/assets/less/ant.less"
    ],
    server: ["./client/app/assets/less/server.less"]
  },
  output: {
    path: path.join(basePath, "./dist"),
    filename: isProduction ? "[name].[chunkhash].js" : "[name].js",
    publicPath: staticPath
  },
  resolve: {
    symlinks: false,
    extensions: [".js", ".jsx", ".ts", ".tsx"],
    alias: {
      'lodash': path.resolve(process.cwd(), 'node_modules', 'lodash'),
      'moment': path.resolve(process.cwd(), 'node_modules', 'moment'),
      'axios': path.resolve(process.cwd(), 'node_modules', 'axios'),
      'js-cookie': path.resolve(process.cwd(), 'node_modules', 'js-cookie'),
      'font-awesome': path.resolve(process.cwd(), 'node_modules', 'font-awesome'),
      'classnames': path.resolve(process.cwd(), 'node_modules', 'classnames'),
      'dompurify': path.resolve(process.cwd(), 'node_modules', 'dompurify'),
      'debug': path.resolve(process.cwd(), 'node_modules', 'debug'),
      'numeral': path.resolve(process.cwd(), 'node_modules', 'numeral'),
      'unorm': path.resolve(process.cwd(), 'node_modules', 'unorm'),
      'uslug': path.resolve(process.cwd(), 'node_modules', 'uslug'),
      'regl': path.resolve(process.cwd(), 'node_modules', 'regl'),
      'bn.js': path.resolve(process.cwd(), 'node_modules', 'bn.js'),
      "@": appPath,
      extensions: extensionPath
    }
  },
  node: {
    fs: "empty"
  },
  // externals: {
  //   React: 'react',
  //   ReactDOM: 'react-dom',
  //   'antd': 'antd'
  // },  
  plugins: [
    new WebpackBuildNotifierPlugin({ title: "首页" }),
    // bundle only default `moment` locale (`en`)
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/),
    new HtmlWebpackPlugin({
      template: "./client/app/index.html",
      filename: "index.html",
      excludeChunks: ["server"],
      release: process.env.BUILD_VERSION || "dev",
      staticPath,
      baseHref,
      title: htmlTitle
    }),
    new HtmlWebpackPlugin({
      template: "./client/app/multi_org.html",
      filename: "multi_org.html",
      excludeChunks: ["server"],
      title: htmlTitle
    }),
    new MiniCssExtractPlugin({
      filename: "[name].[chunkhash].css"
    }),
    new ManifestPlugin({
      fileName: "asset-manifest.json",
      publicPath: ""
    }),
    new CopyWebpackPlugin([
      { from: "client/app/assets/robots.txt" },
      { from: "client/app/unsupported.html" },
      { from: "client/app/unsupportedRedirect.js" },
      { from: "client/app/assets/css/*.css", to: "styles/", flatten: true },
      { from: "client/app/assets/fonts", to: "fonts/" }
    ]),
    // new CompressionWebpackPlugin({
    //   filename: '[path][name].gz[query]',
    //   algorithm: 'gzip',
    //   test: productionGzipExtensions,
    //   threshold: 0,
    //   minRatio: 0.8,
    // }),
  ],
  optimization: {
    minimize: true,
    // minimizer: [new TerserPlugin({
    //   terserOptions: {
    //     ecma: undefined,
    //     warnings: false,
    //     parse: {},
    //     compress: {
    //       drop_console: true,
    //       drop_debugger: false,
    //       pure_funcs: ['console.log'], // 移除console
    //     },
    //   },
    // })],
    runtimeChunk: {
      name: 'runtime'
    },
    splitChunks: {
      maxAsyncRequests: 50,
      maxInitialRequests: 50,  
      chunks: chunk => {
        return chunk.name != "server";
      },
      cacheGroups: {
        "lodash-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/lodash/.test(module.context)),
          priority: 25,
          reuseExistingChunk: true,
          name: 'lodash',
        },
        "moment-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/moment/.test(module.context)),
          priority: 24,
          reuseExistingChunk: true,
          name: 'moment',
        },
        "bn-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/bn.js/.test(module.context)),
          priority: 23,
          reuseExistingChunk: true,
          name: 'bn',
        },
        "unorm-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/unorm?/.test(module.context)),
          priority: 22,
          reuseExistingChunk: true,
          name: 'unorm',
        },
        "uslug-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/uslug?/.test(module.context)),
          priority: 21,
          reuseExistingChunk: true,
          name: 'uslug',
        },
        "regl-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/regl?/.test(module.context)),
          priority: 20,
          reuseExistingChunk: true,
          name: 'regl',
        },
        "react-vendor": {
          test: (module) => {
            debugger;
            return /react/.test(module.context) || /redux/.test(module.context)
            || /classnames/.test(module.context) || /prop-types/.test(module.context)},
          priority: 17,
          reuseExistingChunk: true,
          name: 'react',
        },
        "antd-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/antd?/.test(module.context)),
          priority: 16,
          reuseExistingChunk: true,
          name: 'antd',
        },
        "highlight-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/highlight.js/.test(module.context)),
          priority: 14,
          reuseExistingChunk: true,
          name: 'highlight',
        },
        "emojione-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/emojione?/.test(module.context)),
          priority: 12,
          reuseExistingChunk: true,
          name: 'emojione',
        },
        "markdown-it-icons-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/markdown-it-icons?/.test(module.context)),
          priority: 11,
          reuseExistingChunk: true,
          name: 'markdown-it-icons',
        },
        "katex-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/katex/.test(module.context)),
          priority: 10,
          reuseExistingChunk: true,
          name: 'katex',
        },
        "mermaid-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/mermaid?/.test(module.context)),
          priority: 9,
          reuseExistingChunk: true,
          name: 'mermaid',
        },
        "mapbox-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/mapbox?/.test(module.context)),
          priority: 8,
          reuseExistingChunk: true,
          name: 'mapbox',
        },
        "markdown-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/markdown?/.test(module.context)),
          priority: 7,
          reuseExistingChunk: true,
          name: 'markdown',
        },
        "plotly-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/plotly.js/.test(module.context)),
          priority: 6,
          reuseExistingChunk: true,
          name: 'plotly',
        },
        "ace-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/ace?/.test(module.context)),
          priority: 5,
          reuseExistingChunk: true,
          name: 'ace',
        },
        "viz-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/@redash/.test(module.context)),
          priority: 4,
          reuseExistingChunk: true,
          name: 'viz',
        },        
      }  
    },
  },
  module: {
    rules: [
      {
        test: /\.(t|j)sx?$/,
        exclude: /node_modules/,
        use: ["babel-loader", "eslint-loader"]
      },
      {
        test: /\.html$/,
        exclude: [/node_modules/, /index\.html/, /multi_org\.html/],
        use: [
          {
            loader: "raw-loader"
          }
        ]
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: "css-loader",
            options: {
              minimize: process.env.NODE_ENV === "production"
            }
          }
        ]
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: "css-loader",
            options: {
              minimize: process.env.NODE_ENV === "production"
            }
          },
          {
            loader: "less-loader",
            options: {
              plugins: [
                new LessPluginAutoPrefix({ browsers: ["last 3 versions"] })
              ],
              javascriptEnabled: true
            }
          }
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        use: [
          {
            loader: "file-loader",
            options: {
              context: path.resolve(appPath, "./assets/images/"),
              outputPath: "images/",
              name: "[path][name].[ext]"
            }
          }
        ]
      },
      {
        test: /\.geo\.json$/,
        type: "javascript/auto",
        use: [
          {
            loader: "file-loader",
            options: {
              outputPath: "maps/",
              name: "[name].[ext]"
            }
          }
        ]
      },
      // {
      //   test: /emoji\.json$/,
      //   type: "javascript/auto",
      //   use: [
      //     {
      //       loader: "file-loader",
      //       options: {
      //         outputPath: "fonts/",
      //         name: "[name].[ext]"
      //       }
      //     }
      //   ]
      // },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 10000,
              name: "fonts/[name].[hash:7].[ext]"
            }
          }
        ]
      }
    ]
  },
  devtool: 'none',
  stats: {
    children: false,
    modules: false,
    chunkModules: false
  },
  watchOptions: {
    ignored: /\.sw.$/
  },
  devServer: {
    inline: true,
    index: "/static/index.html",
    historyApiFallback: {
      index: "/static/index.html",
      rewrites: [{ from: /./, to: "/static/index.html" }]
    },
    contentBase: false,
    publicPath: staticPath,
    proxy: [
      {
        context: [
          "/login",
          "/logout",
          "/invite",
          "/setup",
          "/status.json",
          "/api",
          "/oauth"
        ],
        target: redashBackend + "/",
        changeOrigin: false,
        secure: false
      },
      {
        context: path => {
          // CSS/JS for server-rendered pages should be served from backend
          return /^\/static\/[a-z]+\.[0-9a-fA-F]+\.(css|js)$/.test(path);
        },
        target: redashBackend + "/",
        changeOrigin: true,
        secure: false
      }
    ],
    stats: {
      modules: false,
      chunkModules: false
    }
  },
  performance: {
    hints: false
  }
};

if (process.env.DEV_SERVER_HOST) {
  config.devServer.host = process.env.DEV_SERVER_HOST;
}

if (process.env.BUNDLE_ANALYZER || isProduction) {
  config.plugins.push(new BundleAnalyzerPlugin());
}

module.exports = maybeApplyOverrides(config);
